#include "CatSpriteLoader.h"

char* CatSpriteLoader::getStatusFileName()
{
	return "Game/Cats/[Cat] Status (100).png";
}

char* CatSpriteLoader::getCatFileName(EnumCatType catType)
{
	switch (catType)
	{
	case BASE_CAT: 		return "Game/Cats/[Cat][Punk] (100).png";
	case BOUNCE_CAT: 	return "Game/Cats/[Cat][Bouncing] (100).png";
	case FAT_CAT:		return "Game/Cats/[Cat][Fat] (100).png";
	case NINJA_CAT: 	return "Game/Cats/[Cat][Ninja] (100).png";
	case OLYMPIC_CAT:	return "Game/Cats/[Cat][Olympic] (100).png";
	case PEW_CAT: 		return "Game/Cats/[Cat][Punk] (100).png";
	case PUNK_CAT:		return "Game/Cats/[Cat][Punk] (100).png";
	case WITCH_CAT:		return "Game/Cats/[Cat][Witch] (100).png";
	default:
		return "Game/Cats/[Cat][Punk] (100).png";
	}
}

int CatSpriteLoader::getCatSpriteWidth(EnumCatType catType, EnumCatAnimation catAnim)
{
	//special case for witch cat skill animation
	if (catType == WITCH_CAT && catAnim == CAT_ANIM_SKILL)
		return 125;
	else
		return SPRITE_WIDTH;
}

int CatSpriteLoader::getCatAnimationRow(EnumCatType catType, EnumCatAnimation catAnim)
{
	switch (catType)
	{
	case BOUNCE_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_BURNT:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_EARTHQUAKE:	return SPRITE_WIDTH * 4;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 3;
		default:					return 0;
		}
	}
	case FAT_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_ZAPPED:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_BURNT:		return SPRITE_WIDTH * 3;
		case CAT_ANIM_EARTHQUAKE: 	return SPRITE_WIDTH * 5;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 4;
		default:					return 0;
		}
	}
	case NINJA_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_ZAPPED:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_EARTHQUAKE:	return SPRITE_WIDTH * 4;
		case CAT_ANIM_SKILL:		return SPRITE_WIDTH * 5;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 3;
		default:					return 0;
		}
	}
	case OLYMPIC_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_ZAPPED:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_BURNT:		return SPRITE_WIDTH * 3;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 4;
		default:					return 0;
		}
	}
	case PEW_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:
		case CAT_ANIM_ZAPPED:
		case CAT_ANIM_BURNT:
		case CAT_ANIM_EARTHQUAKE:
		case CAT_ANIM_SKILL:
		case CAT_ANIM_INJURED:
		default:					return 0;
		}
	}
	case PUNK_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_ZAPPED:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_BURNT:		return SPRITE_WIDTH * 3;
		case CAT_ANIM_SKILL:		return SPRITE_WIDTH * 5;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 4;
		default:					return 0;
		}
	}
	case WITCH_CAT:
	{
		switch (catAnim)
		{
		case CAT_ANIM_WALK:			return 0;
		case CAT_ANIM_ATTACK:		return SPRITE_WIDTH;
		case CAT_ANIM_ZAPPED:		return SPRITE_WIDTH * 2;
		case CAT_ANIM_BURNT:		return SPRITE_WIDTH * 3;
		case CAT_ANIM_SKILL:		return SPRITE_WIDTH * 5;
		case CAT_ANIM_INJURED:		return SPRITE_WIDTH * 4;
		case CAT_ANIM_PROJ_LAUNCH:
		case CAT_ANIM_PROJ_FLY:
		case CAT_ANIM_PROJ_DEATH: 	return SPRITE_WIDTH * 6;
		default:					return 0;
		}
	}
	}
}

int CatSpriteLoader::getCatAnimationFrameCount(EnumCatType catType, EnumCatAnimation catAnim)
{
	switch (catAnim)
	{
	case CAT_ANIM_WALK:			return 4;
	case CAT_ANIM_ATTACK:		return 4;
	case CAT_ANIM_ZAPPED:		return 6;
	case CAT_ANIM_BURNT:		return 7;
	case CAT_ANIM_EARTHQUAKE:	return 4;
	case CAT_ANIM_SKILL:
	{
		switch (catType)
		{
		case PUNK_CAT:			return 6;
		case NINJA_CAT:			return 4;
		case WITCH_CAT:			return 4;
		default:				return 0;
		}
	}
	case CAT_ANIM_INJURED:		return 2;
	case CAT_ANIM_DEATH_BLACK:	return 7;
	case CAT_ANIM_DEATH_WHITE:	return 5;
	case CAT_ANIM_WET:			return 2;
	case CAT_ANIM_IMMUNE:		return 4;
	case CAT_ANIM_PROJ_LAUNCH: 	return 2;
	case CAT_ANIM_PROJ_FLY: 	return 2;
	case CAT_ANIM_PROJ_DEATH: 	return 3;
	default:					return 0;
	}
}

int CatSpriteLoader::getCatEffectsRow(EnumCatAnimation catAnim)
{
	switch(catAnim)
	{
	case CAT_ANIM_DEATH_BLACK: 	return SPRITE_WIDTH;
	case CAT_ANIM_DEATH_WHITE: 	return 0;
	case CAT_ANIM_WET:			return SPRITE_WIDTH * 2;
	case CAT_ANIM_IMMUNE:		return SPRITE_WIDTH * 3;
	}
}

float CatSpriteLoader::getAnimationDuration(EnumCatType catType, EnumCatAnimation catAnim)
{
	return ANIMATION_INTERVAL * getCatAnimationFrameCount(catType, catAnim);
}

CCSpriteFrame* CatSpriteLoader::getSpriteFrame(EnumCatType catType)
{
	return CCSpriteFrame::create(CatSpriteLoader::getCatFileName(catType),
			CCRect(0, getCatAnimationRow(catType, CAT_ANIM_WALK), getCatSpriteWidth(catType, CAT_ANIM_WALK), SPRITE_WIDTH));
}

CCSpriteFrame* CatSpriteLoader::getSpecialSpriteFrame(EnumCatType catType)
{
	if (catType == PUNK_CAT)
		return CCSpriteFrame::create(CatSpriteLoader::getCatFileName(catType),
				CCRect(0, getCatAnimationRow(catType, CAT_ANIM_SKILL), getCatSpriteWidth(catType, CAT_ANIM_SKILL), SPRITE_WIDTH));
	return 0;
}

CCAnimate* CatSpriteLoader::getCatAnimation(EnumCatType catType, EnumCatAnimation catAnim)
{
	//setup variables
	int spriteWidth = getCatSpriteWidth(catType, catAnim);
	int spriteRow = getCatAnimationRow(catType, catAnim);
	int frames = getCatAnimationFrameCount(catType, catAnim);
	char* filename = getCatFileName(catType);

	//check if animation exists
	if(frames == 0)
		return 0;

	//create an animation holder
	CCAnimation *animation = CCAnimation::create();

	//load the frames of the animation
	for (int i = 0; i < frames; i++)
	{
		CCSpriteFrame* animationFrame = CCSpriteFrame::create(filename, CCRect((i * spriteWidth), spriteRow, spriteWidth, SPRITE_WIDTH));
		animation->addSpriteFrame(animationFrame);
	}

	//setup animation properties
	animation->setDelayPerUnit(ANIMATION_INTERVAL);
	//play injured animation once only
	if (catAnim == CAT_ANIM_INJURED)
		animation->setLoops(1);
	else
		animation->setLoops(10000);

	//create the animation and set a tag
	CCAnimate* runnableAnimation = CCAnimate::create(animation);
	runnableAnimation->setTag(SPRITE_CAT_TAG);

	return runnableAnimation;
}

CCAnimate* CatSpriteLoader::getCatStatusAnimation(EnumCatAnimation catAnim)
{
	int spriteWidth = getCatSpriteWidth(BASE_CAT, catAnim);
	int spriteRow = getCatEffectsRow(catAnim);
	int frames = getCatAnimationFrameCount(BASE_CAT, catAnim);
	char* filename = getStatusFileName();
	int loopTimes;

	switch (catAnim)
	{
	case CAT_ANIM_DEATH_BLACK:
	case CAT_ANIM_DEATH_WHITE:
		loopTimes = 1;
	default:
		loopTimes = 100000;
	}

	//check if animation exists
	if (frames == 0)
		return 0;

	//create an animation holder
	CCAnimation *animation = CCAnimation::create();

	//load the frames of the animation
	for (int i = 0; i < frames; i++)
	{
		CCSpriteFrame* animationFrame = CCSpriteFrame::create(filename, CCRect((i * spriteWidth), spriteRow, spriteWidth, SPRITE_WIDTH));
		animation->addSpriteFrame(animationFrame);
	}

	//setup animation properties
	animation->setDelayPerUnit(ANIMATION_INTERVAL);
	animation->setLoops(loopTimes);

	//create the animation and set a tag
	CCAnimate* runnableAnimation = CCAnimate::create(animation);

	return runnableAnimation;
}

CCAnimate* CatSpriteLoader::getCatProjectileAnimation(EnumCatType catType, EnumCatAnimation catAnim)
{
	//setup variables
	int spriteWidth = getCatSpriteWidth(catType, catAnim);
	int spriteRow = getCatAnimationRow(catType, catAnim);
	int frames = getCatAnimationFrameCount(catType, catAnim);
	char* filename = getCatFileName(catType);

	int spriteStart;
	switch(catAnim)
	{
	case CAT_ANIM_PROJ_LAUNCH:
		spriteStart = 0;
		break;
	case CAT_ANIM_PROJ_FLY:
		spriteStart = getCatAnimationFrameCount(catType, CAT_ANIM_PROJ_LAUNCH);
		break;
	case CAT_ANIM_PROJ_DEATH:
		spriteStart = getCatAnimationFrameCount(catType, CAT_ANIM_PROJ_LAUNCH) + getCatAnimationFrameCount(catType, CAT_ANIM_PROJ_FLY);
		break;
	default:
		spriteStart = 0;
	}

	//check if animation exists
	if(frames == 0)
		return 0;

	//create an animation holder
	CCAnimation *animation = CCAnimation::create();

	//load the frames of the animation
	for (int i = 0; i < frames; i++)
	{
		CCSpriteFrame* animationFrame = CCSpriteFrame::create(filename, CCRect((spriteStart * spriteWidth) + (i * spriteWidth), spriteRow, spriteWidth, SPRITE_WIDTH));
		animation->addSpriteFrame(animationFrame);
	}

	//setup animation properties
	animation->setDelayPerUnit(ANIMATION_INTERVAL);
	//play injured animation once only
	if (catAnim == CAT_ANIM_PROJ_LAUNCH || catAnim == CAT_ANIM_PROJ_DEATH)
		animation->setLoops(1);
	else
		animation->setLoops(10000);

	//create the animation and set a tag
	CCAnimate* runnableAnimation = CCAnimate::create(animation);
	return runnableAnimation;

}

void CatSpriteLoader::preloadSpriteSheets()
{
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(BOUNCE_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(FAT_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(PUNK_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(NINJA_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(WITCH_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(OLYMPIC_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getCatFileName(PEW_CAT));
	CCTextureCache::sharedTextureCache()->addImage(CatSpriteLoader::getStatusFileName());
}
